package com.jian.mall.sevice.impl;

import com.alibaba.fastjson.JSON;
import com.jian.mall.common.redis.User;
import com.jian.mall.common.utils.R;
import com.jian.mall.feign.ProduceFeign;
import com.jian.mall.interceptor.CartInterceptor;
import com.jian.mall.sevice.CartService;
import com.jian.mall.vo.AddToCartInfo;
import com.jian.mall.vo.CartItem;
import com.jian.mall.vo.CartVo;
import com.jian.mall.vo.SkuInfoTo;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ProduceFeign produceFeign;
    @Autowired
    private ThreadPoolExecutor executor;

    public final String CART_KEY = "cart:";

    @Override
    public void addToCart(AddToCartInfo cartInfo) throws ExecutionException, InterruptedException {
        CartItem item = new CartItem();
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();

        Object value = hashOps.get(cartInfo.getSkuId().toString());
        if (value != null) {
            CartItem info = JSON.parseObject((String) value, CartItem.class);
            if (info.getNumber() != null && cartInfo.getNumber() != null)
                info.setNumber(info.getNumber() + cartInfo.getNumber());
            info.setTotalPrice(info.getTotalPrice());
            hashOps.put(info.getSkuId().toString(), JSON.toJSONString(info));
            return;
        }

        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            // 设置购物车基本属性
            R info = produceFeign.info(cartInfo.getSkuId());
            SkuInfoTo skuInfo = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(info.get("skuInfo"))), SkuInfoTo.class);
            item.setSkuId(skuInfo.getSkuId());
            item.setImage(skuInfo.getSkuDefaultImg());
            item.setPrice(skuInfo.getPrice());
            item.setChecked(true);
            item.setTitle(skuInfo.getSkuTitle());
            item.setTotalPrice(item.getTotalPrice());
            item.setNumber(cartInfo.getNumber());

        }, executor);
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            // 设置购物车的销售属性值
            List<String> attrBySkuId = produceFeign.saleAttrBySkuId(cartInfo.getSkuId());
            item.setAttrs(attrBySkuId);
        }, executor);
        CompletableFuture.allOf(future1, future2).get();

        hashOps.put(item.getSkuId().toString(), JSON.toJSONString(item));
    }

    @NotNull
    private BoundHashOperations<String, Object, Object> getHashOps() {
        User user = CartInterceptor.userInfoThreadLocal.get();
        return redisTemplate.boundHashOps(CART_KEY + user.getId());
    }

    @Override
    public CartVo getAllCartInfo(User info) {
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();
        List<Object> list = hashOps.values();
        List<CartItem> itemList = null;
        if (list != null && list.size() > 0) {
            itemList = list.stream().map((m) ->
                    JSON.parseObject((String) m, CartItem.class)).collect(Collectors.toList());
        }
        CartVo cartVo = new CartVo();
        cartVo.setCartItems(itemList);
        cartVo.setCheckedCount(cartVo.getCheckedCount());
        cartVo.setTotalCount(cartVo.getTotalCount());
        cartVo.setTotalPrice(cartVo.getTotalPrice());
        return cartVo;
    }

    @Override
    public void cleanCart() {
        User user = CartInterceptor.userInfoThreadLocal.get();
        if (user.getId() != null) {
            String key = CART_KEY + user.getId();
            redisTemplate.delete(key);
        }
    }

    @Override
    public void updateCartItem(CartItem cartItem) {
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();
        Object o = hashOps.get(cartItem.getSkuId().toString());
        if (o == null) return;
        CartItem item = JSON.parseObject((String) o, CartItem.class);
        item.setNumber(cartItem.getNumber());
        item.setChecked(cartItem.getChecked());

        hashOps.put(cartItem.getSkuId().toString(), JSON.toJSONString(item));
    }

    @Override
    public void deleteByCartSkuId(Long cartId) {
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();
        if (cartId != null && Boolean.TRUE.equals(hashOps.hasKey(cartId.toString()))) {
            hashOps.delete(cartId.toString());
        }
    }

    @Override
    public void deleteByCartSkuIds(List<Long> skuIds) {
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();
        hashOps.delete(skuIds.stream().map(Object::toString).collect(Collectors.toList()));
    }

    @Override
    public List<CartItem> getSelective() {
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();
        List<Object> list = hashOps.values();
        List<CartItem> itemList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            List<CartItem> collect = list.stream().map(m -> {
                String json = (String) m;
                return JSON.parseObject(json, CartItem.class);
            }).collect(Collectors.toList());

            for (CartItem item : collect) {
                if (item.getChecked() != null && item.getChecked()){
                    itemList.add(item);
                }
            }
        }

        return itemList;
    }
}
